namespace SharpTalk.Core
{
    using System;
    using Enums;
    using Interfaces;
    using System.Runtime.Serialization;
    using Base;

    [DataContract]
    [Serializable]
    public sealed class ChatRoomDetails : PropertyChangedBase, IEquatable<ChatRoomDetails>, ICloneable
    {
        private byte[] _image;
        private ChatRoomTypeEnum _type;
        private string _motd;

        public ChatRoomDetails()
        {
            Guid = System.Guid.NewGuid();
        }

        public ChatRoomDetails(Guid guid)
        {
            Guid = guid;
        }

        public ChatRoomDetails(IChatRoom chatRoom)
        {
            this.Guid = chatRoom.Guid;
            this.Name = chatRoom.Name;
            this.Image = chatRoom.Image;
            this.Type = chatRoom.Type;
            this.Motd = chatRoom.Motd;
        }

        [DataMember(IsRequired = true)]
        public Guid Guid { get; set; }
        [DataMember(IsRequired = true)]
        public string Name { get; set; }

        [DataMember]
        public byte[] Image
        {
            get { return _image; }
            set { _image = value; NotifyPropertyChange(() => Image); }
        }

        [DataMember(IsRequired = true)]
        public ChatRoomTypeEnum Type
        {
            get { return _type; }
            set
            {
                _type = value; 
                NotifyPropertyChange(() => Type);
            }
        }

        [DataMember]
        public string Motd
        {
            get { return _motd; }
            set { _motd = value; NotifyPropertyChange(() => Motd); }
        }

        [DataMember]
        public Guid Owner { get; set; }

        /// <summary>
        /// Indicates whether the current object is equal to another object of the same type.
        /// </summary>
        /// <returns>
        /// true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.
        /// </returns>
        /// <param name="other">An object to compare with this object.</param>
        public bool Equals(ChatRoomDetails other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return other.Guid.Equals(Guid);
        }

        /// <summary>
        /// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
        /// </summary>
        /// <returns>
        /// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
        /// </returns>
        /// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>. </param><filterpriority>2</filterpriority>
        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != typeof (ChatRoomDetails)) return false;
            return Equals((ChatRoomDetails) obj);
        }

        /// <summary>
        /// Serves as a hash function for a particular type. 
        /// </summary>
        /// <returns>
        /// A hash code for the current <see cref="T:System.Object"/>.
        /// </returns>
        /// <filterpriority>2</filterpriority>
        public override int GetHashCode()
        {
            return Guid.GetHashCode();
        }

        /// <summary>
        /// Creates a new object that is a copy of the current instance.
        /// </summary>
        /// <returns>
        /// A new object that is a copy of this instance.
        /// </returns>
        /// <filterpriority>2</filterpriority>
        public object Clone()
        {
            return new ChatRoomDetails(Guid)
                       {
                           Name = this.Name,
                           Image = this.Image,
                           Type = this.Type,
                           Owner = this.Owner,
                           Motd = this.Motd,
                       };
        }

        public static bool operator ==(ChatRoomDetails left, ChatRoomDetails right)
        {
            return Equals(left, right);
        }

        public static bool operator !=(ChatRoomDetails left, ChatRoomDetails right)
        {
            return !Equals(left, right);
        }
    }
}